package com.qd.system.service.menu;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cdqidi.exception.ApiException;
import com.qd.common.sys.constant.Constants;
import com.qd.common.sys.domain.entity.meun.MenuDTO;
import com.qd.common.sys.domain.entity.role.RoleDTO;
import com.qd.common.sys.util.SecurityUtils;
import com.qd.system.service.person.PersonRoleService;
import com.qd.system.service.role.RoleMenuService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static java.util.stream.Collectors.toList;

/**
 * 菜单操作
 *
 * @author sjk
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class MenuHoldService {
    private final MenuService menuService;
    private final RoleMenuService roleMenuService;
    private final PersonRoleService personRoleService;

    @Transactional(rollbackFor = Exception.class)
    public void removeById(String menuId) throws ApiException {
        removeMenu(menuId);
    }

    @Transactional(rollbackFor = Exception.class)
    public void removeByIds(List<String> menuIds) throws ApiException {
        menuIds.forEach(this::removeMenu);
    }

    @Transactional(readOnly = true)
    public MenuDTO getMenuInfoAndRoleInfo(String menuId) {
        final MenuDTO menuDto = menuService.getByIdDto(menuId);
        if (null != menuDto) {
            QueryWrapper<?> wrapper = new QueryWrapper<>();
            wrapper.eq("rm.menu_id", menuId);
            final List<RoleDTO> roleList = roleMenuService.getBaseMapper().getRoleByMenuId(wrapper);
            if (null != roleList && !roleList.isEmpty()) {
                menuDto.setRoleList(roleList);
            }
            wrapper.clear();
        }
        return menuDto;
    }

    /**
     * 获得人员对应的菜单信息
     *
     * @param personId 人员ID
     * @return 菜单列表
     */
    @Transactional(readOnly = true)
    public List<MenuDTO> getMenuList(String personId) {
        List<MenuDTO> menus = menuService.getMenuTreeAll();
        if (menus.isEmpty()) {
            throw new ApiException("没有配置菜单信息");
        }
        final List<MenuDTO> menuList = menus.stream().filter(menuDto -> {
            if (null != menuDto.getMenuStatus()) {
                return menuDto.getMenuStatus() == Constants.STATUS_ENABLE;
            }
            return false;
        }).collect(toList());
        if (menuList.isEmpty()) {
            throw new ApiException("没有配置菜单信息");
        }
        return getMenus(personId, menuList);
    }

    @Transactional(readOnly = true)
    public List<MenuDTO> getChildren(MenuDTO menu) {
        return menuService.getBaseMapper().getMenuTreeAll(menuService.createQueryWrapper(menu));
    }

    private void removeMenu(String menuId) {
        if (menuService.hasChildByMenuId(menuId)) {
            throw new ApiException("存在子菜单，不允许删除");
        }
        if (roleMenuService.checkMenuExistRole(menuId)) {
            throw new ApiException("菜单已分配,不允许删除");
        }
        menuService.removeById(menuId);
    }

    private List<MenuDTO> getMenus(String personId, List<MenuDTO> menuList) {
        if (SecurityUtils.isAdmin(personId)) {
            return menuList;
        } else {
            final List<RoleDTO> roleList = personRoleService.getRoleByPersonId(personId);
            if (null == roleList || roleList.isEmpty()) {
                log.info("当前登录人不存在对应的角色信息,personId{}",personId);
                return Collections.emptyList();
            }
            List<String> roleMenuList = new ArrayList<>();
            roleList.forEach(role -> {
                final List<String> menuStrList = roleMenuService.getMenuStrByRoleId(role.getRoleId());
                if (null != menuStrList && !menuStrList.isEmpty()) {
                    roleMenuList.addAll(menuStrList);
                }
            });
            if (roleMenuList.isEmpty()) {
                log.info("当前登录人对应的角色信息没有配置菜单,personId: " + personId + "角色列表: " + Arrays.toString(roleList.stream().map(RoleDTO::getRoleId).toArray()));
                return Collections.emptyList();
            }
            return menuList.stream().filter(menu -> roleMenuList.contains(menu.getMenuId())).collect(toList());
        }
    }
}